#include <BPlusTreeLeafsStorage.hpp>
using namespace FTSS;

BPlusTreeLeaf* BPlusTreeLeafsStorage::GetLeafById(INT_32 leaf_id){
	INT_32 page_size = sysconf(_SC_PAGE_SIZE);
	if (leaf_id < length_data){
		INT_32 offset = page_size * leaf_id / sizeof(INT_64);
		INT_64 cur_id = storage_data_mmap[offset + 2];
		// check leaf id
		if (cur_id != leaf_id){
			fprintf(stderr , "except : leaf_id=%d, restored_leaf_id=%lld, data=%s\n", leaf_id, cur_id, (CHAR_P)(storage_data_mmap + offset + 3));
			 throw LogicException("trouble with storage GetLeafById leaf_id != restored leaf_id");
		}
		// create new Leaf
		INT_64 cur_size = storage_data_mmap[offset + 3];
		BPlusTreeLeaf *pRes = new BPlusTreeLeaf(cur_size,
							cur_id);
		//copy data to leaf
		INT_32 size_to_copy = page_size / sizeof(INT_64) - 4;
		if (cur_size + 1 < size_to_copy) size_to_copy = cur_size + 1;
		memcpy( pRes->data,
			(void *) (storage_data_mmap + offset  + 4),
		        size_to_copy);

		return pRes;
	}
	return NULL;
}

/**	
 * DumpNode to white space of storage or to the end of file
 * and generate node id and return it
*/
INT_32 BPlusTreeLeafsStorage::DumpLeaf(BPlusTreeLeaf *pLeaf){
	INT_32 current_leaf_id;
	if (pLeaf->leaf_id == -1) {
		current_leaf_id = pLeaf->leaf_id;
		if (current_leaf_id > length_data) length_data = current_leaf_id;
	} else if (length_stack != 0){
		current_leaf_id = vector_data_mmap[length_stack + 1];
		--length_stack;
	} else {
		current_leaf_id = length_data;
		++length_data;
	}
	INT_32 page_size = sysconf(_SC_PAGE_SIZE);
	//remmaping
//	fprintf(stderr, "size_storage_nodes=%d, index=%d\n", size_storage_nodes, page_size * current_leaf_id + 1);
	if ( page_size *( current_leaf_id + 1) >= size_storage_nodes ){
		if (ReMMAP(data_storageHandler) != 0)
 			throw UnixException(errno, "remmap leaf storage fails");
	}
	// little optimization
	INT_32 offset = page_size * current_leaf_id / sizeof(INT_64);
	INT_32 size_to_copy = page_size / sizeof(INT_64) - 3;
	//dumping addtitional info
	storage_data_mmap[offset + 2] = current_leaf_id;
	storage_data_mmap[offset + 3] = pLeaf->data_size;
	// + 1 just for safe :-) and little optimization again
	if (pLeaf->data_size + 1 < size_to_copy) size_to_copy = pLeaf->data_size + 1;
	// dump page with information
	memcpy((void *) (storage_data_mmap + offset  + 4),
	       pLeaf->data,
	       size_to_copy);
//	fprintf(stderr, "memcpy dest=%s, src=%s\n", (CHAR_P)(storage_data_mmap + offset + 3), pNode->data);
	return current_leaf_id;
}

INT_32  BPlusTreeLeafsStorage::DeleteLeaf(INT_32 leaf_id){
	if (length_stack + 2 >= (size_vector_file / sizeof(INT_64))){
		if (ReMMAP(vector_empty_blocksHandler) != 0)
			throw UnixException(errno, "remmap vector empty block fails");
	}
        if (leaf_id < length_data){
                vector_data_mmap[length_stack + 2] = leaf_id;
		++length_stack;
		return 0;
	}
        return -1;
}

